package com.gandong8.trace.tool.service.impl;

import com.gandong8.trace.tool.domain.ResponseData;
import com.gandong8.trace.tool.domain.RequestData;
import com.gandong8.trace.tool.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.stereotype.Service;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service("okHttpService")
public class OkHttpService extends HttpPublicService  {

    @Override
    ResponseData doBoth(RequestData requestData) throws Exception {
        Request request = buildRequest(requestData);
        OkHttpClient client =  buildClient(requestData);
        Response response = client.newCall(request).execute();
        if(!response.isSuccessful()) {
            return new ResponseData();
        }
        ResponseData responseData = new ResponseData();
        responseData.setData(Objects.requireNonNull(response.body()).string());
        responseData.setHttpStatusCode(response.code());
        return responseData;
    }


    /**
     * RequestBody的数据格式都要指定Content-Type，常见的有三种：
     *    1. application/x-www-form-urlencoded 数据是个普通表单
     *    2. multipart/form-data 数据里有文件
     *    3. application/json 数据是个json
     * @param requestData 请求数据
     * @return Request
     */
    private Request buildRequest(RequestData requestData) {
        Request.Builder builder = new Request.Builder().url(requestData.getUrl());
        if(requestData.getHeaders() != null) {
            requestData.getHeaders().forEach(builder::addHeader);
        }
        if(requestData.isGet()) {
            return builder.build();
        }
        RequestBody body;
        if(requestData.getPostJson() != null) {
            body = RequestBody.create( MediaType.parse("application/json; charset=utf-8"), requestData.getPostJson());
        } else {
            //FormBody继承了RequestBody，它已经指定了数据类型为application/x-www-form-urlencoded。
            FormBody.Builder formBodyBuilder = new FormBody.Builder();
            if(requestData.getPostParams() != null) {
                requestData.getPostParams().forEach(formBodyBuilder::add);
            }
            body = formBodyBuilder.build();
        }
        return builder.post(body).build();
    }

    private  OkHttpClient buildClient(RequestData requestData) throws NoSuchAlgorithmException, KeyManagementException {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(requestData.getConnectTimeout(), TimeUnit.SECONDS);
        builder.readTimeout(requestData.getSocketTimeout(), TimeUnit.SECONDS);
        if(!requestData.isHttps()) {
            return builder.build();
        }
        TrustManager[] trustAllCerts = HttpUtil.buildTrustManagers();
        final SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
        builder.hostnameVerifier((hostname, session) -> true);
        return builder.build();
    }


}
